Imports necesarios para la correcta ejecución del Notebook.
# Trabajo con dataframes
import pandas as pd
# Lectura de datos
from pandas import read_csv
# Mapa de calor
import seaborn as sn
# Plots, visualización de gráficas
import matplotlib.pyplot as plt
# Arrays
import numpy as np
# Lectura de directorio
import os
# Normalización de los datos
from sklearn.preprocessing import MinMaxScaler
# Gráficos
import plotly.express as px
import plotly
import flask
Lectura del conjunto de datos obtenido de la pagina de salud de Murcia https://www.murciasalud.es/pagina.php?id=458869 Recogidos desde el 08/03/2020 hasta el dia 25/03/2020.
lectura = read_csv('../Datos_originales/casos_diarios_total_regional.csv', skiprows = 4, encoding='latin-1', sep = ';', na_values = ['NaN', 'NaT'])
# Headers = columnas de mi conjunto de datos. Si no especificamos asume que son las de la primera fila leida
# Skiprows = n: con n = numero de filas que quiero saltar. Las cuatro primeras son texto -> las saltamos
# Encoding = 'latin-1': para que no de errores de codificacion de algunos caracteres
# Sep = ';': delimitador que separa las columnas
# Index_col = 0: usar la primera columna (fechas) como filas del dataframe
Renombramos los nombres de algunas de las columnas para que queden mas compactos.
datos = lectura.rename(columns={'Pruebas_PCR_Ag':'Pruebas',
'Casos_incidentes_PCR/Ag+':'Incidentes',
'Hospitalizados': 'H',
'Hospitaliz_UCI':'H_UCI',
'Asintomatico_hombre_<45años': 'Asint_H_<45',
'Asintomatico_hombre_45a64años': 'Asint_H_45a64',
'Asintomatico_hombre_+65años': 'Asint_H_+65',
'Sintomatico_hombre_<45años': 'Sint_H_<45',
'Sintomatico_hombre_45a64años': 'Sint_H_45a64',
'Sintomatico_hombre_+65años': 'Sint_H_+65',
'Asintomatico_mujer_<45años': 'Asint_M_<45',
'Asintomatico_mujer_45a64años': 'Asint_M_45a64',
'Asintomatico_mujer_+65años': 'Asint_M_+65',
'Sintomatico_mujer_<45años': 'Sint_M_<45',
'Sintomatico_mujer_45a64años': 'Sint_M_45a64',
'Sintomatico_mujer_+65años': 'Sint_M_+65'})
Convertimos los datos leidos en un dataFrame y lo mostramos para ver su apariencia.
df_salud_murcia = pd.DataFrame(datos)
df_salud_murcia.head(3)
| Fecha | Pruebas | Incidentes | H | H_UCI | Defunciones | Asint_H_<45 | Asint_H_45a64 | Asint_H_+65 | Sint_H_<45 | Sint_H_45a64 | Sint_H_+65 | Asint_M_<45 | Asint_M_45a64 | Asint_M_+65 | Sint_M_<45 | Sint_M_45a64 | Sint_M_+65 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 08/03/2020 | 130.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
| 1 | 09/03/2020 | 21.0 | 3.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3.0 | 0.0 | 0.0 |
| 2 | 10/03/2020 | 39.0 | 6.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 2.0 | 0.0 | 0.0 |
Lo siguiente que haremos es indexar el dataframe por la columna 'Fecha'. Para ello, primero debemos convertir la misma en un objeto de tipo DatatimeIndex. Usamos la funcion 'to_datetime' y le indicamos el formato en el que se encuentran las fechas para que se lea y procese bien. Posteriormente eliminamos la columna del dataFrame e insertamos el nuevo DatatimeIndex como íncide. Finalmente mostramos el resultado.
format = '%d/%m/%Y'
datetime_fecha = pd.to_datetime(df_salud_murcia['Fecha'], format = format)
df_salud_murcia = df_salud_murcia.drop(['Fecha'], axis=1)
df_salud_murcia.insert(0,'Fecha', datetime_fecha)
df_salud_murcia = df_salud_murcia.set_index('Fecha')
df_salud_murcia.head(3)
| Pruebas | Incidentes | H | H_UCI | Defunciones | Asint_H_<45 | Asint_H_45a64 | Asint_H_+65 | Sint_H_<45 | Sint_H_45a64 | Sint_H_+65 | Asint_M_<45 | Asint_M_45a64 | Asint_M_+65 | Sint_M_<45 | Sint_M_45a64 | Sint_M_+65 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Fecha | |||||||||||||||||
| 2020-03-08 | 130.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
| 2020-03-09 | 21.0 | 3.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 3.0 | 0.0 | 0.0 |
| 2020-03-10 | 39.0 | 6.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 2.0 | 0.0 | 0.0 |
Con la siguiente función eliminamos todos aquellos valores que se almacenan o completan como NaN.
df_salud_murcia.dropna(axis = 0, inplace = True)
Sumamos asintomáticos y sintomáticos que estaban repartidos en tres grupos de edades. Eliminamos los grupos y nos quedamos con el total de cada uno en dos nuevas columnas del dataframe.
df_salud_murcia['Asintomaticos'] = df_salud_murcia['Asint_H_<45'] + df_salud_murcia['Asint_H_45a64'] + df_salud_murcia['Asint_H_+65'] + df_salud_murcia['Asint_M_<45'] + df_salud_murcia['Asint_M_45a64'] + df_salud_murcia['Asint_M_+65']
df_salud_murcia['Sintomaticos'] = df_salud_murcia['Sint_H_<45'] + df_salud_murcia['Sint_H_45a64'] + df_salud_murcia['Sint_H_+65'] + df_salud_murcia['Sint_M_<45'] + df_salud_murcia['Sint_M_45a64'] + df_salud_murcia['Sint_M_+65']
df_salud_murcia = df_salud_murcia.drop(['Asint_H_<45', 'Asint_H_45a64', 'Asint_H_+65', 'Asint_M_<45', 'Asint_M_45a64', 'Asint_M_+65', 'Sint_H_<45', 'Sint_H_45a64', 'Sint_H_+65', 'Sint_M_<45', 'Sint_M_45a64', 'Sint_M_+65'], axis=1)
A continuación lo que hacemos es guardarla en un archivo de extensión .csv para poder recuperarla posteriormente.
df_salud_murcia.to_csv(path_or_buf = '../Datos_preprocesados/salud_murcia.csv')
df_salud_murcia = read_csv('../Datos_preprocesados/salud_murcia.csv', encoding='latin-1', sep = ',', na_values = ['NaN', 'NaT'])
df_salud_murcia = df_salud_murcia.set_index('Fecha')
copia = df_salud_murcia.drop(['Pruebas'], axis = 1)
fig = px.box(df_salud_murcia, y = copia.columns)
flask.Markup(fig)
fig.show("notebook")
Necesitamos añadir los datos de movilidad proporcionados por el Ministerio de Transporte y Movilidad en la Región de Murcia. Para ello se buscaron los códigos de los municipios murcianos así como sus correspondientes códigos para el Ministerio, ya que no siempre coinciden.
A continuación se definen las funciones necesarias para el correcto tratamiento de los datos.
La siguiente función permite parsear las fechas, a partir del nombre del fichero obtenemos la fecha correspondiente
def parseador_fechas_mitma(nombre):
# Cogemos el día
dia = nombre[6:8]
# Cogemos el mes
mes = nombre[4:6]
# Cogemos el año
anio = nombre[0:4]
# Escribimos en formato año-dia-mes
return(anio+'-'+dia+'-'+mes)
Al igual que hicimos con el dataframe de los datos de salud que leímos al principio, debemos transformar las fechas en objetos de tipo DatatimeIndex. Posteriormente las ordenaremos para que se muestren en orden cronológico. Para ello usamos la función 'to_datetime', que convierte nuestra lista de fechas en DatatimeIndex. Acto seguido creamos el dataframe con las entradas, las salidas a la Región de Murcia y las fechas y las ponemos como índice del dataframe. Ahora solo queda ordenarlo. Añadimos tres columnas adicionales al dataframe que son los meses, dias y años de las fechas. Ordenamos según estos valores y posteriormente las eliminamos del dataframe. Devolvemos el dataframe construido.
def conversor_a_dataframe(lista_fechas, lista_entradas, lista_salidas):
format = '%Y-%d-%m'
# Convertimos en DatatimeIndex
fechas_serie = pd.to_datetime(lista_fechas, format = format)
# Creamos dataframe con las entradas salidas y fechas
df_entradas_salidas = pd.DataFrame(list(zip(lista_entradas, lista_salidas)), columns = ['Entradas', 'Salidas'], index = fechas_serie).rename_axis('Fecha', axis = 0)
# Definimos las series para ordenar
df_entradas_salidas['month'] = fechas_serie.month
df_entradas_salidas['year'] = fechas_serie.year
df_entradas_salidas['day'] = fechas_serie.day
# Ordenamos por mes-dia-año
df_entradas_salidas = df_entradas_salidas.sort_values(['year', 'month', 'day']).drop(columns=['day', 'month', 'year'])
# Devolvemos el dataframe construido
return df_entradas_salidas
La lista "codigos" contiene todos los códigos de los municipios de la Región con la codificación usada por el Ministerio.
# Los diferentes al resto
codigos = ['30901', '30902']
# Cogemos el resto de códigos de municipios
for i in range(1,44):
if i < 10 and i not in [4,6]:
codigos.append('3000'+str(i))
if i >= 10 and i not in [14,27,29,31,32,34,39,40,42]:
codigos.append('300'+str(i))
if i == 4:
codigos.append('30014_AM')
if i == 6:
codigos.append('30039_AM')
if i == 14:
codigos.append('30014_AM')
if i == 27:
codigos.append('3002701')
if i == 29:
codigos.append('30029_AM')
if i == 31:
codigos.append('30042_AM')
if i == 32:
codigos.append('30029_AM')
if i == 34:
codigos.append('30014_AM')
if i == 39:
codigos.append('30039_AM')
if i == 40:
codigos.append('30042_AM')
if i == 42:
codigos.append('30042_AM')
Lo siguiente que haremos es procesar todos los datos que tenemos. Para cada archivo, nos quedamos con las salidas y entradas en la Región de Murcia, esto es, no se considera la movilidad entre distintos municipios murcianos si no las salidas y entradas de municipios fuera de la Región hacia ella o desde municipios de la Región hasta municipios fuera de ella.
# Ruta hacia el directorio donde se encuentran los archivoss
ruta = '../Datos_originales/mitma_movilidad/'
# Lista para las fechas de recogida de datos
lista_fechas = []
# Lista para almacenar el total de entradas a la Región cada día
lista_entradas = []
# Lista para almacenar el total de salidas de la Región cada día
lista_salidas = []
# Cogemos los archivos .tar mensuales
archivos = os.listdir(ruta)
# Recorremos los archivos
for a in archivos:
meses = os.listdir(ruta+a)
# Cada archivo mensual válido lo procesamos
for m in meses:
# Repetición de archivos con ._ no válidos
if "._" not in m:
# Obtenemos la fecha
fecha = parseador_fechas_mitma(m)
lista_fechas.append(fecha)
# Leemos el archivo correspondiente
df = pd.read_csv(ruta+a+'/'+m, compression='gzip', sep='|', header=0, low_memory = False)
# Nos quedamos solo con las salidas de la Región
df_s = df[df['origen'].isin(codigos)]
# Eliminamos los viajes en la propia Región
df_s = df_s[~df_s['destino'].isin(codigos)]
# Nos quedamos solo con las entradas a la Región
df_e = df[df['destino'].isin(codigos)]
# Eliminamos los viajes en la propia Región
df_e = df_e[~df_e['origen'].isin(codigos)]
# Sumamos todos los viajes que son las entradas y salidas
salidas = df_s['viajes'].sum()
entradas = df_e['viajes'].sum()
# Añadimos a las listas
lista_salidas.append(salidas)
lista_entradas.append(entradas)
Convertimos los datos recogidos en un dataframe mediante la función definida anteriormente.
df_mitma = conversor_a_dataframe(lista_fechas, lista_entradas, lista_salidas)
df_mitma.tail(3)
| Entradas | Salidas | |
|---|---|---|
| Fecha | ||
| 2021-02-26 | 130495.728 | 126471.246 |
| 2021-02-27 | 73285.851 | 71385.928 |
| 2021-02-28 | 49817.997 | 49735.536 |
Vemos ahora el número de filas y el número de missing values.
df_mitma.shape
(374, 2)
df_mitma.isna().sum()
Entradas 0 Salidas 0 dtype: int64
Guardamos el conjunto de datos con la movilidad en un nuevo archivo con extensión csv.
df_mitma.to_csv(path_or_buf = '../Datos_preprocesados/movilidad.csv')
df_mitma = read_csv('../Datos_preprocesados/movilidad.csv', encoding='latin-1', sep = ',', na_values = ['NaN', 'NaT'])
df_mitma = df_mitma.set_index('Fecha')
En este apartado se juntan los dataframe de las dos fuentes de datos que se han procesado. De esta forma, a los datos de salud se le añaden los datos de movilidad generando un nuevo dataframe, que será con el que trabajaremos el resto del proyecto.
df_salud_movilidad = pd.concat([df_salud_murcia, df_mitma], axis=1)
Aparecen nuevos valores missing, debido a las diferentes fechas sobre las que se han recogido los datos.
df_salud_movilidad.head(3)
| Pruebas | Incidentes | H | H_UCI | Defunciones | Asintomaticos | Sintomaticos | Entradas | Salidas | |
|---|---|---|---|---|---|---|---|---|---|
| Fecha | |||||||||
| 2020-02-21 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 166795.814 | 168567.936 |
| 2020-02-22 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 144424.897 | 144077.722 |
| 2020-02-23 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 138142.960 | 133974.435 |
Suprimimos los missing values.
df_salud_movilidad.dropna(axis = 0, inplace = True)
Guardamos en archivo de extensión csv el dataframe.
df_salud_movilidad.to_csv(path_or_buf = '../Datos_preprocesados/salud_movilidad.csv')
df_salud_movilidad = read_csv('../Datos_preprocesados/salud_movilidad.csv', encoding='latin-1', sep = ',', na_values = ['NaN', 'NaT'])
df_salud_movilidad = df_salud_movilidad.set_index('Fecha')
Contamos de nuevo las filas y el número de missing values y los eliminamos.
df_salud_movilidad.shape
(358, 9)
df_salud_movilidad.isna().sum()
Pruebas 0 Incidentes 0 H 0 H_UCI 0 Defunciones 0 Asintomaticos 0 Sintomaticos 0 Entradas 0 Salidas 0 dtype: int64
for column in df_salud_movilidad:
# Cogemos la serie correspondientes
serie = df_salud_movilidad[column]
# Dibujamos
fig = px.line(serie, x = df_salud_movilidad.index, y = column, width = 700, height = 400)
flask.Markup(fig)
fig.show("notebook")